#include "mainwindow.h"
#include "mypacketmodel.h"
#include <deque>

extern std::deque<PPACKET> bufferDeque;

extern HANDLE hMutex;
extern bool stopThreads;

///////////////////////////////////////////////////////////////////////
//// Dirty, temporary

#include <QDebug>
#define cout qDebug()

///////////////////////////////////////////////////////////////////////

HANDLE CompletionPort;


#define PACKS_NUMBER 16


DWORD WINAPI WorkerThread(LPVOID CompletionPortID)
{
	HANDLE r, hDevice;
	DWORD BytesTransferred, dwBytesReturned;	
	PPACKET packets[PACKS_NUMBER], newPacket;
	PHANDLE_DATA pHandleData;
	DWORD dwWaitResult, i;


	if ((pHandleData = (PHANDLE_DATA) GlobalAlloc(GPTR,sizeof(HANDLE_DATA))) == NULL)
		cout<<("GlobalAlloc() error %d\n", GetLastError());


	for (i=0; i<PACKS_NUMBER; ++i)
	{
		if ((packets[i] = (PPACKET) GlobalAlloc(GPTR,sizeof(PACKET))) == NULL)
			cout<<("GlobalAlloc() error %d\n", GetLastError());
		ZeroMemory(&(packets[i]->Overlapped), sizeof(OVERLAPPED));
	}

	

	


	if ((CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1)) == NULL)
	{
		cout<<( "Error CreateIoCompletionPort: %d\n", GetLastError());
		return 0;
	}
	hDevice = CreateFile(L"\\\\.\\CtrlUsbSniffer", 0, NULL, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);

	if(hDevice == INVALID_HANDLE_VALUE)
	{
		cout<<"fuck";
	}

	if (CreateIoCompletionPort(hDevice, CompletionPort, (ULONG_PTR)pHandleData, 1) == NULL)
	{
		cout<<("CreateIoCompletionPort Error %d\n", GetLastError());
	}




	for (i=0; i<PACKS_NUMBER-1; ++i)
	{
		DeviceIoControl(hDevice, IOCTL_SET_TRANSPORT_PACKET, NULL, 0, packets[i]->Buffer, SIZE_OF_PACKET, 
			NULL, &(packets[i]->Overlapped));
	}


	while(true)
	{
		dwWaitResult = WaitForSingleObject(hMutex, 5000L);
			if (dwWaitResult == WAIT_TIMEOUT)
			{
				return 1;
			}
			if (stopThreads)
			{
				break;
			}
		ReleaseMutex(hMutex);

		if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred,
			(LPDWORD)&pHandleData, (LPOVERLAPPED *) &packets[0], INFINITE) == 0)
		{
			cout<<("GetQueuedCompletionStatus error! %d!\n", GetLastError());
			continue;
		}

		DeviceIoControl(hDevice, IOCTL_SET_TRANSPORT_PACKET, NULL, 0, packets[PACKS_NUMBER-1]->Buffer, SIZE_OF_PACKET, 
			NULL, &(packets[PACKS_NUMBER-1]->Overlapped));

		//////////////////////////////////////////////////////////////////////////
		//////////////////////////////////////////////////////////////////////////
		if ((newPacket = (PPACKET) GlobalAlloc(GPTR,sizeof(PACKET))) == NULL)
			cout<<("GlobalAlloc() error %d\n", GetLastError());
		ZeroMemory(&(newPacket->Overlapped), sizeof(OVERLAPPED));

		dwWaitResult = WaitForSingleObject(hMutex, 5000L);
			if (dwWaitResult == WAIT_TIMEOUT)
			{
				return 1;
			}
			bufferDeque.push_back(packets[0]);			
		ReleaseMutex(hMutex);
		packets[0] = newPacket;
		//////////////////////////////////////////////////////////////////////////
		//////////////////////////////////////////////////////////////////////////


		for (i=1; i<PACKS_NUMBER; ++i)
		{
			if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred,
				(LPDWORD)&pHandleData, (LPOVERLAPPED *) &packets[i], INFINITE) == 0)
			{
				cout<<("GetQueuedCompletionStatus error! %d!\n", GetLastError());
				continue;
			}

			DeviceIoControl(hDevice, IOCTL_SET_TRANSPORT_PACKET, NULL, 0, packets[i-1]->Buffer, SIZE_OF_PACKET, 
				NULL, &(packets[i-1]->Overlapped));

			//////////////////////////////////////////////////////////////////////////
			//////////////////////////////////////////////////////////////////////////
			if ((newPacket = (PPACKET) GlobalAlloc(GPTR,sizeof(PACKET))) == NULL)
				cout<<("GlobalAlloc() error %d\n", GetLastError());
			ZeroMemory(&(newPacket->Overlapped), sizeof(OVERLAPPED));

			dwWaitResult = WaitForSingleObject(hMutex, 5000L);
				if (dwWaitResult == WAIT_TIMEOUT)
				{
					return 1;
				}
				bufferDeque.push_back(packets[i]);
			ReleaseMutex(hMutex);
			packets[i] = newPacket;
		}
	}

	CloseHandle(hDevice);
	//if(GlobalFree(pHandleData))
	//	cout<<("GlobalFree() error %d\n", GetLastError());

// 	for (i=0; i<PACKS_NUMBER; ++i)
// 	{
// 		if(GlobalFree(packets[i]))
// 			cout<<("GlobalFree() error %d\n", GetLastError());
// 	}

	return 0;
}